package router

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"service/utils"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

// 用户类
type Client struct {
	ID     string
	Socket *websocket.Conn
}

// 用户管理
type ClientManager struct {
	Clients    map[string]*Client
	Broadcast  chan *Broadcast
	Register   chan *Client
	Unregister chan *Client
}

// 广播类，包括广播内容和源用户
type Broadcast struct {
	Client  *Client
	Message []byte
	Type    int
}

var Manager = ClientManager{
	Clients:    make(map[string]*Client), // 参与连接的用户，出于性能的考虑，需要设置最大连接数
	Register:   make(chan *Client),
	Unregister: make(chan *Client),
	Broadcast:  make(chan *Broadcast),
}

func UseSocketRouter(router *gin.Engine) {
	router.GET("/ws", func(ctx *gin.Context) {
		token := ctx.Query("token")
		conn, err := (&websocket.Upgrader{
			CheckOrigin: func(r *http.Request) bool { // CheckOrigin解决跨域问题
				return true
			}}).Upgrade(ctx.Writer, ctx.Request, nil) // 升级成ws协议
		if err != nil {
			utils.HandleFailResponse(ctx, "升级WS失败", err.Error())
			return
		}
		// 创建一个用户实例
		client := &Client{
			ID:     token,
			Socket: conn,
		}
		// 用户注册到用户管理上
		Manager.Register <- client
		Manager.Broadcast <- &Broadcast{
			Type:   1,
			Client: client,
		}
		fmt.Println("=> end")
		go client.Read()
	})

}
func (c *Client) Read() {
	for {
		_, p, err := c.Socket.ReadMessage() // 读取json格式，如果不是json格式，会报错Read
		fmt.Println("=; ", string(p))
		switch string(p) {
		case "fetch order":
			Manager.Broadcast <- &Broadcast{
				Type:   1,
				Client: c,
			}
		}
		if err != nil {
			Manager.Unregister <- c
			Manager.Broadcast <- &Broadcast{
				Type:   2,
				Client: c,
			}
			break
		}
	}
}
func (manager *ClientManager) Start() {
	for {
		select {
		case conn := <-Manager.Register: // 建立连接
			Manager.Clients[conn.ID] = conn
		case conn := <-Manager.Unregister: // 断开连接
			conn.Socket.Close()
			delete(Manager.Clients, conn.ID)
			// log.Println("=> 连接失败  发送了广播", conn)
			//广播信息
		case broadcast := <-Manager.Broadcast:
			if broadcast.Type == 1 {
				clients := []Client{}
				for _, v := range manager.Clients {
					clients = append(clients, *v)
				}
				y, _ := json.Marshal(utils.MsgInfo{
					Type: "SaveMember",
					Msg:  "",
					Data: clients,
				})

				for _, v := range manager.Clients {
					err := v.Socket.WriteMessage(websocket.TextMessage, y)
					log.Println("=> err", err)
				}
			}

		}
	}
}
